#pragma once

#define _USE_MATH_DEFINES

#include <math.h>
#include <stdlib.h>
#include <memory.h>
#include <time.h>
#include <set>
#include <vector>
#include <windows.h>
#include "resource.h"
#include <shellapi.h>
#include <atlbase.h>
#include <algorithm>
#include <map>
#include <list>
#include <commctrl.h>
#include <Commdlg.h>
#include <float.h>

using namespace std;

typedef vector<float> FLOATVECTOR;

typedef unsigned char BYTE;

#define _180BYPI	57.27272727
#define	_PIBY180	0.01746031

#define MAX_STR_SIZE 10

#define BOUNDS(a,x,y)	((a < x) ? x : ((a > y) ? y : a))
#define INTENSITY(r,g,b) (r * 0.30 + g * 0.59 + b * 0.11 + 0.001)

#define EPSILON (1.0e-5F)

#define MagickEpsilon  (1.0e-10F)
#define MaxRGB  (16777216U)
#define QuantumScale  ((float) 1.0/(float) MaxRGB)
#define PixelIntensity(ptPixel) ((float)(0.299 * (ptPixel)->rgbtRed + 0.587 * (ptPixel)->rgbtGreen + 0.114 * (ptPixel)->rgbtBlue + 0.5))
#define RAND_FLOAT ((float)rand() / (float)RAND_MAX)
#define CUBE_ANGLE -0.7853975F

class ConvMatrix;

typedef struct _tagOffPoint
{
	float fx;
	float fy;
}OFFPOINT;

typedef struct _tagStride
{
	int Stride1Left;
	int Stride1Mid;
	int Stride1Right;

	int Stride2Left;
	int Stride2Mid;
	int Stride2Right;
}STRIDE;


typedef struct tagRGB24 
{
        BYTE    rgbtBlue;
        BYTE    rgbtGreen;
        BYTE    rgbtRed;
} RGB24;

typedef struct tagVector
{
  float fx,fy,fz;
} Vector;

typedef struct tagConfig
{
	int iSimpleBrightness;
	struct tagSetGammaValue
	{
		float fpred;
		float fpgreen;
		float fpblue;
	}SetGammaValue;
	struct tagSimpleColorMani
	{
		int ipred;
		int ipgreen;
		int ipblue;
	}SimpleColorMani;
	int iEdgeEnhance;
	int iEdgeDetectDifference;
	int iEdgeDetectHomogenity;
	struct tagTriangle
	{
		int iSize;
		int iWeight;
	}Triangle;
	struct tagFuzzyZoom
	{
		int iMidX;
		int iMidY;
		int iZoom;
	}FuzzyZoom;
	int iOffWave;
	int iOffRNDJitter;
	float OffSwirl;
	float fOffTimeWarp;
	struct tagOffPixelate
	{
		int iPixel;
		BOOL bGrid;
	}OffPixelate;
	int iOffVibration;
	int iOffHoneyComb;
	struct tagOffFlip
	{
		BOOL bHorz;
		BOOL bVert;
	}OffFlip;
	int iSimpleIntContrast;
    int iSimpleFloatContrast;
	struct tagBrightContrastSaturationTint
	{
		int iValue;
		int iCValue;
		int iSaturation;
		int idx;
		int idy;
		int iTint;
	}BrightContrastSaturationTint;
	struct tagCharcoal
	{
		float fAngle;
		float fFreq;
	}Charcoal;
	struct tagPen
	{
		int iStroke;
		int iDirH;
		int iDirV;
	}Pen;
	float fRotationDegree;
	int iBolssomSize;
	struct tagWrinkle
	{
        float fMaxSize;
		BOOL bHorz;
	}Wrinkle;
	struct tagGlass
	{
        int iGlassWidth;
		float fRefractScale;
	}Galss;
	int	iBorderWidth;
    struct tagZoom
	{
		float fRadius;
		int iZoomMidX;
		int iZoomMidY;
		float fMagnifyFactor;
	}Zoom;
	struct tagMesh
	{
        int iMaxOff;
		int iMeshsize;
		BOOL bEnableBackGround;
		RGB24 stLineColor;
	}Mesh;
	struct tagScamble
	{
        int iScrambleNumber;
		int iSideLength;
	}Scamble;
	struct tagPastel
	{
		int iStroke;
		int iThick;
		BOOL bLeft;
		BOOL bRight;
	}Pastel;
	struct tagMotionBlur
	{
        int iMaxBlur;
		int iIteration;
		int iCenX;
        int iCenY;
	}MotionBlur;
	struct tagWaterWave
	{
        int iOffset;
		float fMaxScaleX;
		float fFreqControl;
	}WaterWave;
	struct tagVibrate
	{
        int iHorzDisplacement;
		int iVertDisplacement;
	}Vibrate;
	struct tagUnNoise
	{
		float fMean;
		float fVariance;
	}UnNoise;
	struct tagTwril
	{
        float fAngle;
		int iCenterX,iCenterY;
	}Twril;
	int iTileScale;
	struct tagStretch
	{
		float fScaleLeft;
		float fScaleRight;
		float fScaleTop;
		float fScaleBottom;
	}Stretch;
	int iSpread;
	struct tagSphere
	{
        int iHorzShift;
		int iVertShift;
	}Sphere;
	struct tagRipple
	{
		int iOffset;
		float fFreq;
		int iCenX,iCenY;
	}Ripple;
	struct tagOil
	{
        int iSizeX;
		int iSizeY;
	}Oil;
	struct tagRaise
	{
        int iSideLength;
		int iMaxRaise;
		float fFactor;
	}Raise;
	struct tagLight
	{
        float fRadius;
		int iLightX,iLightY,iLightZ;
		RGB24 stColor;
	}Light;
	struct tagLevel
	{
        int iError;
		int iElevation;
		RGB24 stColor;
	}Level;
	int iDizzy;
	struct tagConcave
	{
        float fMaxConvex;
		float fRadius;
	}Concave;
	struct tagConvex
	{
		float fMaxConvex;
		float fRadius;
	}Convex;
	struct tagPush
	{
		BOOL bHorz;
		float fMaxScale;
	}Push;
	struct tagPull
	{
		BOOL bHorz;
		float fMaxScale;
	}Pull;
	float fPinch;
	struct tagNova
	{
		int iNspoke;
		int iRadius;
		RGB24 stColor;
	}Nova;
	struct tagCentralRefelection
	{
		BOOL bFlip;
		int iRadius;
	}CentralRefelection;
	struct tagWhirl
	{
		float fAngle;
		float fRadius;
		int iCenX,iCenY;
	}Whirl;
	BYTE byBileveImageChannel;
	RGB24 stColorfy;
	float fIllusion;
	struct tagKaleidoscope
	{
		int iNsegs;
		BOOL bFillBlack;
		float fAngle1;
		float fAngle2;
		int iCenX,iCenY;
	}Kaleidoscope;
	struct tagGnoise
	{
		float fVariance;
		float fMean;
	}Gnoise;
	struct tagHighlite
	{
		int iBrightDiff;
		int iElliptic;
		int iHighX,iHighY,iLowX,iLowY;
	}Highlite;
	struct tagLayer
	{
		int iLayerNumber;
		float fMinScale;
		float fStepX,fStepY,fAngleStep;
	}Layer;
	struct tagMosaic
	{
		int iBlockWidth;
		int iLowX,iLowY,iHighX,iHighY;
	}Mosaic;
	int iNewsPaper;
	int iSaturation;
	struct tagThermo
	{
		int bThermoR,bThermoG,bThermoB;
	}Thermo;
	int iTint;
	int iImpress;
	struct tagConicalAnamorphoseDistortion
	{
		float fRadius;
		float fAngle;
		BOOL bFlip;
	}ConicalAnamorphoseDistortion;
	struct tagCurtain
	{
		BOOL bHoriz;
		BOOL bVert;
	}Curtain;
	int iGrid;
	struct tagFog
	{
		float fFogScale;
		RGB24 stRGBColor;
	}Fog;
	int iDarkerStep;
	int iSimpleBlurStrength;
	RGB24 stLineArtLineColor;
    struct tagSinMagic
	{
		int iFrequency;
		int iAmplitude;
	}SinMagic;
	RGB24 stMovieLineArtLineColor;
	int iShadowStrength;
	struct tagBrightContrast
	{
		int iValue;
		int iConstValue;
	}BrightContrast;
	struct tagFishEye
	{
		BOOL bInverse;
		float fCurvature;  //fCurvature = 0.001 * iCurvature; curvature [0.001,0.1],iCurvature will return [1,100]
	}FishEye;
}CONFIG;

//BOOL CALLBACK Configproc(HWND,UINT,WPARAM,LPARAM);
//BOOL CALLBACK ConfigMainproc(HWND,UINT,WPARAM,LPARAM);

class CImageFilter
{

private:

	RGB24 *pStart,*pEnd;
	int cxImage,cyImage,numPixels;
	int ix,iy;
	BYTE m_redgamma[256];
	BYTE m_greengamma[256];
	BYTE m_bluegamma[256];
	CONFIG m_cfg;
	BOOL fResChange;
	int m_currentoption;

	HWND m_hwnd;                          // Window handle for the page
    HWND m_hwndChild;                     // Actual dialog window handle
    int m_DialogId;                       // Dialog resource identifier
	int m_MainDialogID;
	BOOL isReady;

	BOOL bCriticalSectionFlag;

  
public:

	CImageFilter(void);
	~CImageFilter(void);
	void SelectFilter(int iOption);
	int SetData(void * pFirst,int itXres,int itYres);
	void Invert(void);
	void DoubleLine(void);
	void Gray(void);
	void Yellow(void);
	void Xray(void);
	void Mirror(void);
	void CrossOver(void);
	void FourWay(void);
	void TwoWay(void);
	void Fog(float fFogScale , RGB24 stRGBColor);
	void Sepia(void);
	void Distroit(void);
	void LineDetect(void);
	void RedPlanet(void);
	void Jerk(void);
	void ThreshHold(void);
	void UpDown(void);
	void Darker(int iStep);
	void StrongPostrise(void);
	void Postrise(void);
	void SimpleBlur(int iStrangth);
	void SimpleEmboss(void);
	void LineArt(RGB24 stLineColor);
	void DeInterlace(void);
	void D2ActUpdown(void);
	void LakeReflection(void);
	void Tile(void);
	void Tile4(void);
	void SinMagic(int iFrequency,int iAmplitude);
	void ReduseColor(void);
	void MovieLineArt(RGB24 stLineColor);
	void DoubleActHz(void);
	void Tile2(void);
	void Tile2Mirror(void);
	void DoubleactX(void);
	void BlueMagnet(void);
	void Distrotion(void);
	void Grid(int iWidth);
	void Shadow(int iStrength);
	void SimpleSmooth(void);
	void SimpleBrightness(int iValue = 0);
	int SetGammaValue(float fpred,float fpgreen,float fpblue);
	void Gamma(void);
	int SimpleColorMani(int ipred,int ipgreen,int ipblue);
	int Conv3x3(ConvMatrix & m);
	int OffsetFilter(OFFPOINT *ptOffPoint,BOOL bEnableBilinearFilter);
	int OffsetFilterWithBlackFill(OFFPOINT *ptOffPoint,BOOL bEnableBilinearFilter);
	int EdgeEnhance(int iThreshold = 50);
	int EdgeDetectDifference(int iThreshold = 50);
	int EdgeDetectHomogenity(int iThreshold = 0);
	int Antialias();
	int Triangle(int iSize = 20,int iWeight = 125);
	int FuzzyZoom(int iMidX = 50,int iMidY = 75,int iZoom = 16);
	int SimpleEdgeDetecton(void);
	void SimpleEdgeEnhancement(void);
	void BlueChannel(void);
	void RedChannel(void);
	void GreenChannel(void);
	void Test(void);
	void OffWave(int iWave = 5);
	void OffRNDJitter(int iDegree = 10);
	void OffSwirl(float fDegree = 0.05);
	void OffSphere(void);
	void OffTimeWarp(float fFactor);
	void OffPixelate(int iPixel = 15, BOOL bGrid = TRUE);
	void OffVibration(int iDegree = 35);
	void OffHoneyComb(int iSize = 5);
	void OffFlip(BOOL bHorz = TRUE, BOOL bVert = TRUE);
	void SimpleIntContrast(int iValue);
	void SimpleFloatContrast(int iValue);
	void BrightContrast(int iValue, int iConstValue);
	void BrightContrastSaturationTint(int iValue, int iConstValue, int iSaturation, int idx, int idy);
	void GrayScaleVectorMethod(void);
	void GrayScaleSimpleAvg(void);
	void GrayScaleWeightedAvg(void);
	void GrayScalePALNTSCMethod(void);
	void GrayScaleITUR(void);
	void UtlReverseBuffer(RGB24 * pBuf,int iLength);
	int UtlBilinear(float fx, float fy,RGB24 * pDestBuf,RGB24 * pSrcBuf);
	void Charcoal(float fAngle = 60, float fFreq = 5);
	void Pen(int iStroke = 4, int iDirH = 1, int iDirV = 1);
	void Rotation(float fDegree = 60);
	void Bolssom(int iSize = 50);
	void Wrinkle(float fMaxSize = 10, BOOL bHorz = FALSE);
	void Glass(int iGlassWidth = 4, float fRefractScale = .6F);
	void UtlDrawSimpleLine(int ix1, int iy1, int ix2, int iy2,RGB24 stLineColor);
	void UtlLineBresenham(int ix1, int iy1, int ix2, int iy2,RGB24 stLineColor);
	void UtlLineFast(int ix1, int iy1, int ix2, int iy2,RGB24 stLineColor);
	void Border(int iBorderWidth = 10);
	void Zoom(float fRadius, int iZoomMidX, int iZoomMidY, float fMagnifyFactor);
	void Mesh(int iMaxOff, int iMeshsize, BOOL bEnableBackGround , RGB24 stLineColor);
	void Sketch(void);
	void Scramble(int iScrambleNumber = 100, int iSideLength = 20);
	void Pastel(int iStroke = 8, int iThick = 8, BOOL bLeft = TRUE, BOOL bRight = FALSE);
	void MotionBlur(int iMaxBlur, int iIteration, int iCenX, int iCenY);
	int  UtlFloatFill(float fx, float fy,RGB24* ptDestRGB,RGB24 * ptRGB);
	void UtlFloatSphereFill(float fx, float fy , RGB24 *ptDestRGB,RGB24 *ptRGB);
	void WaterWave(int iOffset = 20, float fMaxScaleX = 1.0F, float fFreqControl = 15.0F);
	void Vibrate(int iHorzDisplacement = 5, int iVertDisplacement = 5);
	void UnNoise(float fMean = .0F, float fVariance = 800.0F);
	void Twirl(float fAngle, int iCenterX, int iCenterY);
	void Tile(int iTileScale);
	void Stretch(float fScaleLeft = .8F, float fScaleRight = 1.0F, float fScaleTop = .7F, float fScaleBottom = 1.0F);
	void Spread(int iSpreadDist = 50);
	void Sphere(int iHorzShift = 0, int iVertShift = 0);
	void Ripple(int iOffset, float fFreq, int iCenX, int iCenY);
	void Cube();
	void Oil(int iSizeX = 6, int iSizeY = 6);
	void Raise(int iSideLength = 20, int iMaxRaise = 15, float fFactor = .7F);
	void Light(float fRadius, int iLightX, int iLightY, int iLightZ,RGB24 stColor);
	void Level(int iError, int iElevation,RGB24 stColor);
	void Dizzy(int iBubble = 6);
	void Concave(float fMaxConvex = 4.5F, float fRadius = 30.0F);
	void Convex(float fMaxConvex = 4.5F, float fRadius = 30.0F);
	void Push(BOOL bHorz = TRUE, float fMaxScale = 4.5F);
	void Pull(BOOL bHorz = TRUE, float fMaxScale = 4.5F);
	void Pinch(float fAmount = .5F);
	float Gauss(void);
	void Nova(int iNspoke, int iRadius,RGB24 stColor);
	BYTE UtlGetBrightness(RGB24 *ptRGB);
	BYTE UtlMax(RGB24 *ptRGB);
	BYTE UtlMin(RGB24 *ptRGB);
	void UtlMandelBrot(float fx, float fy, float& fu, float& fv,int iDepth);
	Vector UtlCrossProduct(Vector a, Vector b);
	void UtlNormalize(Vector &a);
	void UtlMulVector(Vector &stResult,float b);
	void UtlSubVector(Vector &stResult,Vector &a,Vector &b);
	void UtlAddVector(Vector &stResult,Vector &a,Vector &b);
	void CentralRefelection(BOOL bFlip, int iRadius);
	void Whirl(float fAngle, float fRadius, int iCenX, int iCenY);
	void BileveImageChannel(unsigned char byThreshold);
	void Colorfy(RGB24 stColor);
	void Illusion(float fDivision);
	void Kaleidoscope(int iNsegs, BOOL bFillBlack, float fAngle1, float fAngle2, int iCenX, int iCenY);
	void AdaptiveUnsharpMasking(void);
	void LaplacianFilterA(void);
	void LaplacianFilterB(void);
	void LaplacianFilterC(void);
	void GaussianBlurA(void);
	void GaussianBlurB(void);
	void GaussianBlurC(void);
	void GaussianBlurD(void);
	void UnSharpen(void);
	void SharpenA(void);
	void SharpenB(void);
	void SharpenC(void);
	void EdgeDetectA(void);
	void EdgeDetectB(void);
	void EdgeDetectC(void);
	void EdgeDetectD(void);
	void EdgeDetectE(void);
	void EdgeDetectF(void);
	void EdgeDetectG(void);
	void EdgeDetectH(void);
	void EdgeDetectI(void);
	void EdgeDetectJ(void);
	void EdgeDetectHV(void);
	void EdgeDetectAll(void);
	void EdgeDetectLossy(void);
	void EdgeDetectHoriz(void);
	void EdgeDetectVert(void);
	void EdgeDetectEast(void);
	void EdgeDetectSouthEastA(void);
	void EdgeDetectSouthEastB(void);
	void EdgeDetectSouth(void);
	void SobellHoriz(void);
	void SobellVert(void);
	void PrewittHoriz(void);
	void PrewittVert(void);
	void KirschA(void);
	void KirschB(void);
	void KirschC(void);
	void KirschD(void);
	void RobinsonA(void);
	void RobinsonB(void);
	void RobinsonC(void);
	void BoxBlur(void);
	void TriangleBlur(void);
	void MeanRemoval(void);
	void EmbossLaplascian(void);
	void InitDafaultValue(void);
	void SetResolution(int iXRes, int iYRes);
	void SetDataPointer(void * pFirst);
	int UtlAntialias(float fx, float fy,RGB24 * pDestBuf,RGB24 * pSrcBuf);
	void Gnoise(float fVariance = 400.0F, float fMean = 0.0F);
	void Highlite(int iBrightDiff, int iElliptic, int iHighX, int iHighY, int iLowX, int iLowY);
	void Layer(int iLayerNumber, float fMinScale, float fStepX, float fStepY, float fAngleStep);
	void Mosaic(int iBlockWidth, int iLowX, int iLowY, int iHighX, int iHighY);
	void NewsPaper(int iSelection);
	void Saturation(int iSaturation);
	void Thermo(int bThermoR, int bThermoG, int bThermoB);
	void Tint(int iTintAngle);
	void Impress(int iRadius);
	void ContrastAutostretch(void);
	void ConicalAnamorphoseDistortion(float fRadius, float fAngle, BOOL bFlip);
	void Caricature(void);
	void FishEye(BOOL bInverse , float fCurvature);
	void Solarization(void);
	void Melt(void);
	void BathRoom(void);
	void ReliefMap(void);
	void Curtain(BOOL bHoriz, BOOL bVert);
	void SelectConfigFilter(void);
	static BOOL CALLBACK Configproc(HWND,UINT,WPARAM,LPARAM);
	static BOOL CALLBACK ConfigMainproc(HWND,UINT,WPARAM,LPARAM);
	BOOL ConfigMessage(HWND,UINT,WPARAM,LPARAM);
	void HandleInitDialogMessage(HWND hwnd,LPARAM lparam);
	void HandleChangeMessage(HWND hwnd);
	BYTE UtlGray(RGB24 ptRGB);
	void FuzzyEdgeDetection(void);
	void FuzzyEdgeEnhancement(void);
};

class ConvMatrix
{

public:

	int TopLeft, TopMid, TopRight;
	int MidLeft, Pixel, MidRight;
	int BottomLeft, BottomMid, BottomRight;
	int Factor;		//The total value of the matrix is divided by a factor
	int Offset;		//offset is added to the end value

	ConvMatrix()
	{
		TopLeft = 0, TopMid = 0, TopRight = 0;				//0 0 0
		MidLeft = 0, Pixel = 1, MidRight = 0;				//0 1 0
		BottomLeft = 0, BottomMid = 0, BottomRight = 0;		//0 0 0
		Factor = 1;
		Offset = 0;
	}

	void SetAll(int nVal)
	{
		TopLeft = TopMid = TopRight = MidLeft = Pixel = MidRight = BottomLeft = BottomMid = BottomRight = nVal;
	}

};
